package com.wa.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.google.common.base.Joiner;
import com.wa.annotation.*;
import com.wa.bean.BasicAllchipsLog;
import com.wa.enums.LogModuleEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 日志处理工具类
 * @Author Dawn
 * @Date 2021/10/26 14:55
 */
@Slf4j
public class AllchipsLogUtils {

    // value占位符
    private final static String VALUE_PLACEHOLDER = "%value%";

    /**
     * 将数据统一转成字符串（list将转成逗号分隔字符串，日期会自动格式化成年月日时分秒）
     * @Author Dawn
     * @Date 2021/10/26 14:52
     */
    public static String toString(Object fieldValue){
        String value = "";
        if(CommUtils.isNotNull(fieldValue)){
            // 日期类型
            if (fieldValue instanceof Date) {
                value = DateUtil.formatDateTime((Date) fieldValue);
            }

            // list类型
            else if (fieldValue instanceof List) {
                if (CollUtil.isNotEmpty((List<String>) fieldValue)) {
                    value = Joiner.on(",").join((List<String>) fieldValue);
                }
            }
            // 数组类型
            else if (fieldValue.getClass().isArray()) {
                if (((String[]) fieldValue).length > 0) {
                    value = Joiner.on(",").join((String[]) fieldValue);
                }
            }
            // 其他类型统一作字符串处理
            else {
                value = fieldValue.toString();
            }
        }
        return value;
    }

    /**
     * 根据注解配置处理日志实体id及实体名称
     * @Author Dawn
     * @Date 2021/10/26 14:48
     */
    public static void processLogEntityInfo(Object dataObject, Class<? extends Annotation> annType, BasicAllchipsLog basicAllchipsLog, LogModuleEnum logModule){
        if (annType == null || annType.equals(AllchipsLogObject.class)){

            List<Object> childrenObjectList = new ArrayList<>();

            Field[] fields = dataObject.getClass().getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                Annotation[] annotations = field.getAnnotations();
                for (Annotation ann : annotations){
                    // 当前为日志实体id
                    if (ann.annotationType().equals(AllchipsLogEntityId.class)
                            && validLogModule(logModule, ((AllchipsLogEntityId) ann).module())){
                        basicAllchipsLog.setEntityId(CommUtils.toLong(getFieldValueStr(dataObject, field)));
                    }
                    // 当前为日志实体名称
                    if (ann.annotationType().equals(AllchipsLogEntityName.class)
                            && validLogModule(logModule, ((AllchipsLogEntityName) ann).module())){
                        basicAllchipsLog.setEntityName(getFieldValueStr(dataObject, field));
                    }
                    // 当前为日志对象，表示还可以继续往下一层查找
                    if (ann.annotationType().equals(AllchipsLogObject.class)
                            && validLogModule(logModule, ((AllchipsLogObject) ann).module())){
                        Object childrenObject = getFieldValue(dataObject, field);
                        if (childrenObject != null){
                            childrenObjectList.add(childrenObject);
                        }
                    }
                }
            }
            if (CommUtils.isNull(basicAllchipsLog.getEntityId())
                    && CommUtils.isEmpty(basicAllchipsLog.getEntityName())
                    && CollUtil.isNotEmpty(childrenObjectList)){
                // 继续下一层查找
                for (Object children : childrenObjectList){
                    processLogEntityInfo(children, AllchipsLogObject.class, basicAllchipsLog, logModule);
                    if (CommUtils.isNull(basicAllchipsLog.getEntityId())
                            && CommUtils.isEmpty(basicAllchipsLog.getEntityName())){
                        return;
                    }
                }
            }
        }
    }

    /**
     * 根据注解配置获取日志内容
     * @Author Dawn
     * @Date 2021/10/25 11:41
     */
    public static String getLogContent(Object dataObject, Class<? extends Annotation> annType, LogModuleEnum logModule) {
        if (dataObject == null){
            return null;
        }
        List<String> fieldValueList = new ArrayList<>();
        Field[] fields = dataObject.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            Annotation[] annotations = field.getAnnotations();
            for (Annotation ann : annotations){
                String value = null;

                // 如果外部对象为null（顶级对象），或外部对象为AllchipsLogObject，查找下级AllchipsLogObject、AllchipsLogProperty、AllchipsLogRelationObject
                if (annType == null || annType.equals(AllchipsLogObject.class)){
                    // 当前为日志对象
                    if (ann.annotationType().equals(AllchipsLogObject.class)
                            && validLogModule(logModule, ((AllchipsLogObject) ann).module())){
                        value = processObject(dataObject, field, (AllchipsLogObject) ann, logModule);
                    }
                    // 当前为日志属性
                    if (ann.annotationType().equals(AllchipsLogProperty.class)
                            && validLogModule(logModule, ((AllchipsLogProperty) ann).module())){
                        value = processProperty(dataObject, field, (AllchipsLogProperty) ann);
                    }
                    // 当前为日志对象关联对象
                    if (ann.annotationType().equals(AllchipsLogRelationObject.class)
                            && validLogModule(logModule, ((AllchipsLogRelationObject) ann).module())){
                        value = processRelationObject(dataObject, field, (AllchipsLogRelationObject) ann, logModule);
                    }
                }

                // 如果外部对象为AllchipsLogRelationObject，查找下级AllchipsLogRelationProperty
                else if (annType.equals(AllchipsLogRelationObject.class)){
                    // 当前字段为日志对象关联对象属性
                    if (ann.annotationType().equals(AllchipsLogRelationProperty.class)
                            && validLogModule(logModule, ((AllchipsLogRelationProperty) ann).module())){
                        value = processRelationProperty(dataObject, field, (AllchipsLogRelationProperty) ann);
                    }
                }

                if (CommUtils.isNotEmpty(value)){
                    fieldValueList.add(value);
                }
            }
        }
        if (CollectionUtils.isEmpty(fieldValueList)){
            return null;
        }
        return Joiner.on("、").join(fieldValueList);
    }

    /**
     * 处理配置为日志对象的值
     * @Author Dawn
     * @Date 2021/10/25 14:54
     */
    public static String processObject(Object dataObject, Field field, AllchipsLogObject allchipsLogObject, LogModuleEnum logModule){
        return getObjectContent(dataObject, field, allchipsLogObject.annotationType(), allchipsLogObject.name(), logModule);
    }

    /**
     * 处理配置为日志对象关联对象的值
     * @Author Dawn
     * @Date 2021/10/27 10:22
     */
    public static String processRelationObject(Object dataObject, Field field, AllchipsLogRelationObject allchipsLogRelationObject, LogModuleEnum logModule){
        return getObjectContent(dataObject, field, allchipsLogRelationObject.annotationType(), allchipsLogRelationObject.name(), logModule);
    }

    /**
     * 处理配置为日志属性的值
     * @Author Dawn
     * @Date 2021/10/25 14:53
     */
    public static String processProperty(Object dataObject, Field field, AllchipsLogProperty allchipsLogProperty) {
        return getFieldContent(dataObject, field, allchipsLogProperty.name());
    }

    /**
     * 处理配置为日志对象关联属性的值
     * @Author Dawn
     * @Date 2021/10/25 14:53
     */
    public static String processRelationProperty(Object dataObject, Field field, AllchipsLogRelationProperty allchipsLogRelationProperty) {
        return getFieldContent(dataObject, field, allchipsLogRelationProperty.name());
    }

    /**
     * 获取对象内容，对象属性名和属性值得拼接字符串
     * @Author Dawn
     * @Date 2021/10/27 11:48
     */
    public static String getObjectContent(Object dataObject, Field field, Class<? extends Annotation> annType, String objectName, LogModuleEnum logModule) {
        try {
            Object fieldObject = field.get(dataObject);
            if (fieldObject instanceof List){
                List<Object> fieldObjectList = (List<Object>) fieldObject;
                if (CollectionUtils.isEmpty(fieldObjectList)){
                    return null;
                }
                List<String> resultList = new ArrayList<>();
                for (Object fo : fieldObjectList) {
                    String content = getLogContent(fo, annType, logModule);
                    if (CommUtils.isNotEmpty(content)){
                        resultList.add(content);
                    }
                }
                if (CollUtil.isNotEmpty(resultList)){
                    if (CommUtils.isEmpty(objectName)){
                        objectName = field.getName();
                    }
                    return objectName + "【"+ Joiner.on("；").join(resultList)+"】";
                }
            }else {
                return getLogContent(fieldObject, annType, logModule);
            }
        } catch (IllegalAccessException e) {
            log.warn("------------------获取{}属性值出错：{}", field.getName(), e);
        }
        return null;
    }

    /**
     * 获取属性内容，属性名和属性值的拼接字符串
     * @Author Dawn
     * @Date 2021/10/27 10:27
     */
    public static String getFieldContent(Object dataObject, Field field, String propertyName){
        String content = propertyName;
        if (CommUtils.isEmpty(content)){
            content = field.getName();
        }
        if (CommUtils.isEmpty(content)){
            return null;
        }else {
            content += "【"+VALUE_PLACEHOLDER+"】";
        }

        return content.replaceAll(VALUE_PLACEHOLDER, getFieldValueStr(dataObject, field));
    }

    /**
     * 获取属性值字符串结果
     * @Author Dawn
     * @Date 2021/10/26 15:28
     */
    public static String getFieldValueStr(Object dataObject, Field field){
        try {
            return AllchipsLogUtils.toString(field.get(dataObject));
        } catch (IllegalAccessException e) {
            log.warn("------------------获取{}属性值出错：{}", field.getName(), e);
        }
        return "";
    }

    /**
     * 获取属性值
     * @Author Dawn
     * @Date 2021/10/29 10:16
     */
    public static Object getFieldValue(Object dataObject, Field field){
        try {
            return field.get(dataObject);
        } catch (IllegalAccessException e) {
            log.warn("------------------获取{}属性值出错：{}", field.getName(), e);
        }
        return null;
    }

    /**
     * 校验属性/对象是否满足加入日志内容的条件
     * @Author Dawn
     * @Date 2021/10/28 17:26
     */
    public static boolean validLogModule(LogModuleEnum logModule, LogModuleEnum[] objectModules){
        if (logModule == null){
            return false;
        }
        if (objectModules != null && objectModules.length > 0){
            List<LogModuleEnum> logModuleEnumList = Arrays.asList(objectModules);
            if (!logModuleEnumList.contains(logModule)){
                return false;
            }
        }
        return true;
    }

}
